package org.zcl.utils;

import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.data.redis.core.StringRedisTemplate;
import org.springframework.data.redis.core.ValueOperations;
import org.springframework.data.redis.core.ZSetOperations;
import org.springframework.data.redis.core.script.DefaultRedisScript;
import org.springframework.data.redis.core.script.RedisScript;
import org.springframework.stereotype.Component;
import org.zcl.entity.RankResponse;

import java.util.ArrayList;
import java.util.List;
import java.util.Objects;
import java.util.Set;

/**
 * .
 *
 * @author zhuchenglin
 * @since 2024/4/22 16:31
 */
@Component
public class RedisHelper {

    @Autowired
    StringRedisTemplate stringRedisTemplate;

    public static final Integer INCREMENT_RANK = 1;

    public Long incrementScore(String key, Long userId) {
        stringRedisTemplate.opsForZSet().incrementScore(key, String.valueOf(userId), INCREMENT_RANK);
        return Objects.requireNonNull(stringRedisTemplate.opsForZSet().score(key, String.valueOf(userId))).longValue();
    }

    public List<RankResponse> list(String key) {
        Set<ZSetOperations.TypedTuple<String>> typedTuples = stringRedisTemplate.opsForZSet().reverseRangeByScoreWithScores(key, 0, 10);
        List<RankResponse> rankResponses = new ArrayList<>();
        assert typedTuples != null;
        for (ZSetOperations.TypedTuple<String> typedTuple : typedTuples) {
            RankResponse rankResponse = new RankResponse();
            rankResponse.setUserId(Long.valueOf(Objects.requireNonNull(typedTuple.getValue())));
            rankResponse.setRank(Objects.requireNonNull(typedTuple.getScore()).longValue());
            rankResponses.add(rankResponse);
        }
        return rankResponses;
    }

    public Long incrNum(String key) {
        ValueOperations<String, String> operations = stringRedisTemplate.opsForValue();
        return operations.increment(key);
    }

    public Boolean deleteKey(String key) {
        return stringRedisTemplate.delete(key);
    }

    public Long executeScript(String script, List<String> keys, List<String> args) {
        RedisScript<Long> redisScript = new DefaultRedisScript<>(script, Long.class);
        return stringRedisTemplate.execute(redisScript, keys, args.toArray());
    }

    public Long getNum(String key) {
        ValueOperations<String, String> ops = stringRedisTemplate.opsForValue();
        String value = ops.get(key);
        return value == null ? 0L : Long.parseLong(value);
    }
}
